import createElement from "./createElement";
import patchVnode from "./patchVnode";

// 检查新旧节点是否为同一个节点
function smallVnode(oldVnode, newVnode) {
    return oldVnode.sel == newVnode.sel && oldVnode.key == newVnode.key
}

export default function updateChildren(parentELm, oldCh, newCh) {
    // 新前
    let newStartIdx = 0;
    // 旧前
    let oldStartIdx = 0;
    // 新后
    let newEndIdx = newCh.length - 1;
    // 旧后
    let oldEndIdx = oldCh.length - 1;
    // 新前节点
    let newStartVnode = newCh[newStartIdx];
    // 旧前节点
    let oldStartVnode = oldCh[oldStartIdx];
    // 新后节点
    let newEndVnode = newCh[newEndIdx]
    // 旧后节点
    let oldEndVnode = oldCh[oldEndIdx]
    let keyMap; // 寻找 keyMap 一个映射对象，
    // 在对于四个进行命中测试
    while (newStartIdx <= newEndIdx && oldStartIdx <= oldEndIdx) {
        console.log("❤");
        if (oldStartVnode == null) {
            oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left
        } else if (oldEndVnode == null) {
            oldEndVnode = oldCh[--oldEndIdx];
        } else if (newStartVnode == null) {
            newStartVnode = newCh[++newStartIdx];
        } else if (newEndVnode == null) {
            newEndVnode = newCh[--newEndIdx];
        } else if (smallVnode(oldStartVnode, newStartVnode)) {
            // (1)新前与旧前
            console.log('(1)新前与旧前')
            patchVnode(oldStartVnode, newStartVnode)
            newStartVnode = newCh[++newStartIdx]
            oldStartVnode = oldCh[++oldStartIdx]
        } else if (smallVnode(oldEndVnode, newEndVnode)) {
            // (2)新后与旧后
            console.log('(2)新后与旧后');
            patchVnode(oldEndVnode, newEndVnode)
            newEndVnode = newCh[--newEndIdx]
            oldEndVnode = oldCh[--oldEndIdx]
        } else if (smallVnode(oldStartVnode, newEndVnode)) {
            // (3)新后与旧前
            console.log('(3)新后与旧前');
            patchVnode(oldStartVnode, newEndVnode)
            parentELm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling)
            newEndVnode = newCh[--newEndIdx]
            oldStartVnode = oldCh[++oldStartIdx]
        } else if (smallVnode(oldEndVnode, newStartVnode)) {
            // (4)新前与旧后
            console.log('(4)新前与旧后');
            patchVnode(oldEndVnode, newStartVnode)
            parentELm.insertBefore(oldEndVnode.elm, oldStartVnode.elm)
            newStartVnode = newCh[++newStartIdx]
            oldEndVnode = oldCh[--oldEndIdx]
        } else {
            if(!keyMap){
                keyMap = {}
                for(let i = oldStartIdx; i <= oldEndIdx; i++) {
                    const key = oldCh[i].key
                    if(key !== undefined)
                    keyMap[key] = i
                }
            }
            console.log(keyMap);
            const idxInOld = keyMap[newStartVnode.key]
            if(idxInOld === undefined){
                // idxInOld 全新项 ，需插入
                parentELm.insertBefore(createElement(newStartVnode), oldStartVnode.elm)
            }else{
                // 说明不是全新项，需要移动
                const elmToMove = oldCh[idxInOld]
                patchVnode(elmToMove, newStartVnode)
                // 把这项设置为 undefined ,表示我已经处理完这项了
                oldCh[idxInOld] = undefined
                // 移动
                parentELm.insertBefore(elmToMove.elm, oldStartVnode.elm)
            }
            newStartVnode = newCh[++newStartIdx];
        }
    }
    //console.log("newStartIdx:" + newStartIdx, "newEndIdx:" + newEndIdx, "oldStartIdx:" + oldStartIdx, "oldEndIdx:" + oldEndIdx);

    // 循环完毕，处理剩余节点
    if (newStartIdx <= newEndIdx) {
        // 新节点还有节点,没有处理（插入）
        // 插入的标杆标杆
        const before = oldCh[oldStartIdx] == null ? null : oldCh[oldStartIdx].elm
        for (let i = newStartIdx; i <= newEndIdx; i++) {
            parentELm.insertBefore(createElement(newCh[i]), before);
        }
    } else if (oldStartIdx <= oldEndIdx) {
        // 旧节点还有剩余（删除）
        for (let i = oldStartIdx; i <= oldEndIdx; i++) {
            if(oldCh[i] != undefined) {
                parentELm.removeChild(oldCh[i].elm);
            }
        }
    }
}